﻿
Imports std

Public Class bare_variable
    Inherits iParseable
    Implements ICloneable

    Public Const stringStart As Char = character.quoteMark
    Public Const stringEnd As Char = character.quoteMark
    Public Const stringEscape As Char = character.rightSlash
    Public Const _true As String = "true"
    Public Const _false As String = "false"
    Private Shared ReadOnly _empty As bare_variable = Nothing
    Private Shared ReadOnly assert_map As assert_map_t = Nothing
    Private Shared ReadOnly assert_set As assert_set_t = Nothing
    Private Shared ReadOnly assert_vector As assert_vector_t = Nothing
    Private Shared ReadOnly assert_list As assert_list_t = Nothing
    Private Shared ReadOnly assert_pointer As assert_pointer_t = Nothing
    Private Shared ReadOnly assert_indep As assert_indep_t = Nothing

    Shared Sub New()
        assert_map = New assert_map_t()
        assert_set = New assert_set_t()
        assert_vector = New assert_vector_t()
        assert_list = New assert_list_t()
        assert_pointer = New assert_pointer_t()
        assert_indep = New assert_indep_t()
        _empty = New bare_variable(typeDefination.unknown, Nothing)
    End Sub

    Public Shared Function empty() As bare_variable
        Return _empty
    End Function

    Protected Friend Shared Function _isMeaningfulMark(ByVal c As Char) As Boolean
        Return c = stringStart OrElse c = stringEnd
    End Function

    Private var As variable = Nothing
    Private v As Object = Nothing

    Public Function value() As Object
        Return v
    End Function

    Public Function variable() As variable
        assert(Not var Is Nothing, "var is nothing")
        Return var
    End Function

    Private Class assert_map_t
        Inherits md_t(Of Object)

        Protected Overrides Function cb(Of ET1 As IComparable(Of ET1), ET2) _
                                       (ByRef i As map(Of ET1, ET2), _
                                        ByRef rtn As Object) As Boolean
            Return Not i Is Nothing
        End Function
    End Class

    Private Class assert_set_t
        Inherits sd_t(Of Object)

        Protected Overrides Function cb(Of ET As IComparable(Of ET)) _
                                       (ByRef i As [set](Of ET), ByRef rtn As Object) As Boolean
            Return Not i Is Nothing
        End Function
    End Class

    Private Class assert_vector_t
        Inherits vd_t(Of Object)

        Protected Overrides Function cb(Of ET)(ByRef i As vector(Of ET), ByRef rtn As Object) As Boolean
            Return Not i Is Nothing
        End Function
    End Class

    Private Class assert_list_t
        Inherits ld_t(Of Object)

        Protected Overrides Function cb(Of ET)(ByRef i As list(Of ET), ByRef rtn As Object) As Boolean
            Return Not i Is Nothing
        End Function
    End Class

    Private Class assert_pointer_t
        Inherits pd_t(Of Object)

        Protected Overrides Function cb(Of ET)(ByRef i As pointer(Of ET), ByRef rtn As Object) As Boolean
            Return Not i Is Nothing
        End Function
    End Class

    Private Class assert_indep_t
        Inherits id_t(Of Object)

        Protected Overrides Function cb(ByVal i As Boolean, ByRef rtn As Object) As Boolean
            Return Not CType(i, Object) Is Nothing
        End Function

        Protected Overrides Function cb(ByVal i As Double, ByRef rtn As Object) As Boolean
            Return Not CType(i, Object) Is Nothing
        End Function

        Protected Overrides Function cb(ByVal i As Int64, ByRef rtn As Object) As Boolean
            Return Not CType(i, Object) Is Nothing
        End Function

        Protected Overrides Function cb(ByVal i As Object, ByRef rtn As Object) As Boolean
            Return True
        End Function

        Protected Overrides Function cb(ByVal i As String, ByRef rtn As Object) As Boolean
            Return True
        End Function

        Protected Overrides Function cb_u(ByVal i As Object, ByRef rtn As Object) As Boolean
            Return i Is Nothing
        End Function
    End Class

    Private Shared Sub assert_typematch(ByVal t As typeDefination, _
                                        ByVal et1 As typeDefination, ByVal et2 As typeDefination, _
                                        ByVal i As Object)
        assert(typeInvoke(Of Object)(i, t, et1, et2, Nothing, _
                                     assert_map, assert_vector, assert_set, assert_list, assert_pointer, assert_indep))
    End Sub

    Private Function invokeImpl(Of RT)(ByRef rtn As RT, _
                                       ByVal md As md_t(Of RT), _
                                       ByVal vd As vd_t(Of RT), _
                                       ByVal sd As sd_t(Of RT), _
                                       ByVal ld As ld_t(Of RT), _
                                       ByVal pd As pd_t(Of RT), _
                                       ByVal id As id_t(Of RT), _
                                       ByVal ParamArray para() As Object) As Boolean
        If value() Is Nothing Then
            Return False
        Else
            Return typeInvoke(value(), variable().type(), variable().elementType1(), variable().elementType2(), rtn, _
                              md, vd, sd, ld, pd, id, para)
        End If
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal pd As pd_t(Of RT), _
                                  ByVal id As id_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(rtn, md, vd, sd, ld, pd, id, para)
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal pd As pd_t(Of RT), _
                                  ByVal id As id_t(Of RT)) As Boolean
        Return invokeImpl(rtn, md, vd, sd, ld, pd, id)
    End Function

    Public Function invoke(Of RT)(ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal pd As pd_t(Of RT), _
                                  ByVal id As id_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(Nothing, md, vd, sd, ld, pd, id, para)
    End Function

    Public Function invoke(Of RT)(ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal pd As pd_t(Of RT), _
                                  ByVal id As id_t(Of RT)) As Boolean
        Return invokeImpl(Nothing, md, vd, sd, ld, pd, id)
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(rtn, md, vd, sd, ld, Nothing, Nothing, para)
    End Function

    Public Function invoke(Of RT)(ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(Nothing, md, vd, sd, ld, Nothing, Nothing, para)
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT)) As Boolean
        Return invokeImpl(rtn, md, vd, sd, ld, Nothing, Nothing)
    End Function

    Public Function invoke(Of RT)(ByVal md As md_t(Of RT), _
                                  ByVal vd As vd_t(Of RT), _
                                  ByVal sd As sd_t(Of RT), _
                                  ByVal ld As ld_t(Of RT)) As Boolean
        Return invokeImpl(Nothing, md, vd, sd, ld, Nothing, Nothing)
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal pd As pd_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(rtn, Nothing, Nothing, Nothing, Nothing, pd, Nothing, para)
    End Function

    Public Function invoke(Of RT)(ByVal pd As pd_t(Of RT), _
                                  ByVal ParamArray para() As Object) As Boolean
        Return invokeImpl(Nothing, Nothing, Nothing, Nothing, Nothing, pd, Nothing, para)
    End Function

    Public Function invoke(Of RT)(ByRef rtn As RT, _
                                  ByVal pd As pd_t(Of RT)) As Boolean
        Return invokeImpl(rtn, Nothing, Nothing, Nothing, Nothing, pd, Nothing)
    End Function

    Public Function invoke(Of RT)(ByVal pd As pd_t(Of RT)) As Boolean
        Return invokeImpl(Nothing, Nothing, Nothing, Nothing, Nothing, pd, Nothing)
    End Function

    Private Sub initial(ByVal t As typeDefination, ByVal et1 As typeDefination, ByVal et2 As typeDefination, _
                        ByVal i As Object)
        assert_typematch(t, et1, et2, i)
        var = New variable(t, et1, et2)
        setvalue(i)
    End Sub

    Public Sub New(ByVal t As variable, ByVal i As Object)
        initial(t.type(), t.elementType1(), t.elementType2(), i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal i As Object)
        initial(t, typeDefination.unknown, typeDefination.unknown, i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal et1 As typeDefination, ByVal i As Object)
        initial(t, et1, typeDefination.unknown, i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal et1 As typeDefination, ByVal et2 As typeDefination, _
                   ByVal i As Object)
        initial(t, et1, et2, i)
    End Sub

    Public Sub New(ByVal i As bare_variable)
        If Not i Is Nothing Then
            initial(i.variable().type(), i.variable().elementType1(), i.variable().elementType2(), i.value())
        End If
    End Sub

    Private Shared Function intfirst(ByVal c As Char) As Boolean
        Return isdigit(c) OrElse c = character.minusSign OrElse c = character.plusSign
    End Function

    Private Shared Function intother(ByVal c As Char) As Boolean
        Return isdigit(c)
    End Function

    Private Shared Function parseIntImpl(ByVal input As String, ByRef index As Int64, _
                                         ByRef output As bare_variable) As Boolean
        Dim s As String = Nothing
        If token(input, index, s, AddressOf intfirst, AddressOf intother) Then
            Dim o As Int64
            If convertor.toint64(s, o) Then
                output = New bare_variable(typeDefination.int, o)
                Return True
            Else
                logparseerror("cannot parse string " + s + " to int", index)
            End If
        End If

        Return False
    End Function

    Private Shared Function parseInt(ByVal input As String, ByRef index As Int64, _
                                     ByRef output As bare_variable) As Boolean
        Return parsebase(input, index, output, AddressOf parseIntImpl, False)
    End Function

    Private Shared Function floatfirst(ByVal c As Char) As Boolean
        Return intfirst(c) OrElse c = character.dot
    End Function

    Private Shared Function floatother(ByVal c As Char) As Boolean
        Return intother(c) OrElse c = character.dot
    End Function

    Private Shared Function parseFloatImpl(ByVal input As String, ByRef index As Int64, _
                                           ByRef output As bare_variable) As Boolean
        Dim s As String = Nothing
        If token(input, index, s, AddressOf floatfirst, AddressOf floatother) Then
            Dim o As Double
            If convertor.todouble(s, o) Then
                output = New bare_variable(typeDefination.float, o)
                Return True
            Else
                logparseerror("cannot parse string " + s + " to float", index)
            End If
        End If

        Return False
    End Function

    Private Shared Function parseFloat(ByVal input As String, ByRef index As Int64, _
                                       ByRef output As bare_variable) As Boolean
        Return parsebase(input, index, output, AddressOf parseFloatImpl, False)
    End Function

    Private Shared Function booleanstart(ByVal s As String, ByVal index As Int64, ByRef inc As Int64) As Boolean
        If strsame(s, index, _true, 0, strlen(_true), False) Then
            inc = strlen(_true)
            Return True
        ElseIf strsame(s, index, _false, 0, strlen(_false), False) Then
            inc = strlen(_false)
            Return True
        Else
            Return False
        End If
    End Function

    Private Shared Function parseBooleanImpl(ByVal input As String, ByRef index As Int64, _
                                             ByRef output As bare_variable) As Boolean
        Dim s As String = Nothing
        If token(input, index, s, AddressOf booleanstart, AddressOf falses) Then
            Dim o As Boolean
            If convertor.toboolean(s, o) Then
                output = New bare_variable(typeDefination.bool, o)
                Return True
            Else
                logparseerror("cannot parse string " + s + " to bool", index)
            End If
        End If

        Return False
    End Function

    Private Shared Function parseBoolean(ByVal input As String, ByRef index As Int64, _
                                         ByRef output As bare_variable) As Boolean
        Return parsebase(input, index, output, AddressOf parseBooleanImpl, False)
    End Function

    Private Shared Function stringFirstChar(ByVal c As Char) As Boolean
        Return c = stringStart
    End Function

#If Not PocketPC AndAlso Not Smartphone Then
    <ThreadStatic()> Private Shared lastchar As Char
#Else
    Private Shared lastchar As Char
#End If

    Private Shared Function stringOtherChar(ByVal c As Char) As Boolean
        If c <> stringEnd OrElse lastchar = stringEscape Then
            If lastchar = stringEscape AndAlso c = stringEscape Then
                lastchar = character.null
            Else
                lastchar = c
            End If
            Return True
        Else
            Return False
        End If
    End Function

    Private Shared Function parseStringImpl(ByVal input As String, ByRef index As Int64, _
                                            ByRef output As bare_variable) As Boolean
        Dim s As String = Nothing
        lastchar = character.null
        If token(input, index, s, AddressOf stringFirstChar, AddressOf stringOtherChar) Then
            index += strlen(stringEnd)
            strrplc(s, stringEscape + stringEscape, stringEscape)
            strrplc(s, stringEscape + stringEnd, stringEnd)
            output = New bare_variable(typeDefination.string, strmid(s, strlen(stringStart)))
            Return True
        Else
            Return False
        End If
    End Function

    Private Shared Function parseString(ByVal input As String, ByRef index As Int64, _
                                        ByRef output As bare_variable) As Boolean
        Return parsebase(input, index, output, AddressOf parseStringImpl, False)
    End Function

    Private Shared Function parseImpl(ByVal input As String, ByRef index As Int64, _
                                      ByRef output As bare_variable) As Boolean
        Return parseBoolean(input, index, output) OrElse _
               parseInt(input, index, output) OrElse _
               parseFloat(input, index, output) OrElse _
               parseString(input, index, output)
    End Function

    Public Shared Function parse(ByVal input As String, ByRef index As Int64, _
                                 ByRef output As bare_variable) As Boolean
        Return parsebase(input, index, output, AddressOf parseImpl)
    End Function

    Public Sub setvalue(ByVal v As Object)
        copy(Me.v, v)
    End Sub

    Public Function [true]() As Boolean
        Select Case variable().type()
            Case typeDefination.bool
                Return value() = True
            Case typeDefination.int
                Return value() <> 0
            Case typeDefination.float
                Return value() <> 0
            Case typeDefination.string
                Return Not isemptystring(Convert.ToString(value()))
            Case Else
                Return Not value() Is Nothing
        End Select
    End Function

    Public Function [false]() As Boolean
        Return Not [true]()
    End Function

    Public Overrides Function ToString() As String
        Return Convert.ToString(variable()) + ":" + Convert.ToString(value())
    End Function

    Public Overridable Function Clone() As Object Implements ICloneable.Clone
        Return New bare_variable(Me)
    End Function

    'set value helper functions
    Public Function setPointerOfString(ByVal s As String, Optional ByVal enableVar As Boolean = True) As Boolean
        If variable().elementType1() = typeDefination.string Then
            convertor.cast(Of elpmis_pointer(Of String))(value()).instance().setinstance(s)
        ElseIf enableVar AndAlso variable().elementType1() = typeDefination.var Then
            convertor.cast(Of elpmis_pointer(Of Object))(value()).instance().setinstance(s)
        Else
            Return False
        End If

        Return True
    End Function

    Public Function setPointerOfInt(ByVal i As Int64, Optional ByVal enableVar As Boolean = True) As Boolean
        If variable().elementType1() = typeDefination.int Then
            convertor.cast(Of elpmis_pointer(Of Int64))(value()).instance().setinstance(i)
        ElseIf enableVar AndAlso variable().elementType1() = typeDefination.var Then
            convertor.cast(Of elpmis_pointer(Of Object))(value()).instance().setinstance(i)
        Else
            Return False
        End If

        Return True
    End Function

    Public Function setPointerOfVar(ByVal i As Object) As Boolean
        If variable().elementType1() = typeDefination.var Then
            convertor.cast(Of elpmis_pointer(Of Object))(value()).instance().setinstance(i)
        Else
            Return False
        End If

        Return True
    End Function
End Class

Public Class const_bare_variable
    Inherits bare_variable

    Public Sub New(ByVal t As variable, ByVal i As Object)
        MyBase.New(t, i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal i As Object)
        MyBase.New(t, i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal et1 As typeDefination, ByVal i As Object)
        MyBase.New(t, et1, i)
    End Sub

    Public Sub New(ByVal t As typeDefination, ByVal et1 As typeDefination, ByVal et2 As typeDefination, _
                   ByVal i As Object)
        MyBase.New(t, et1, et2, i)
    End Sub

    Public Sub New(ByVal i As bare_variable)
        MyBase.New(i)
    End Sub

    Public Shadows Sub setvalue(ByVal v As Object)
        raiseError("should not setvalue to const bare_variable.", errorHandle.errorType.user)
    End Sub

    Public Overrides Function Clone() As Object
        Return Me
    End Function
End Class